<template>
  <div>
    <div class="video-wrapper">
      <video
        :src="videoSrc"
        :autoplay="false"
        :controls="true"
        width="100%"
        class="i-video"
      ></video>
    </div>
    <div>
      <img :src="imageSrc" />
    </div>
    <div>
      <div>{{ messageText }}</div>
      <input
        id="selectfiles"
        type="file"
        accept="video/*"
        @change="handleFileInputChange"
        @click="handleFileInputClick"
      />
    </div>
    <div>
      <p>上传文件大小：{{ uploadFileSize }}</p>
      <p>转码后文件大小：{{ fileSize }}</p>
      <p>转码进度{{ transcodingProgress }}%</p>
      <p>转码计时：{{ time }} 秒</p>
    </div>
    <br />
    <div>
      <div class="file-info">
        <p>文件名：{{ filename }}</p>
        <p>时长：{{ duration }}</p>
        <p>格式：{{ majorBrand }}</p>
        <p>编码器：{{ encoder }}</p>
        <p>分辨率：{{ resolution }}</p>
        <p>比特率：{{ bitRate }}</p>
        <p>帧率：{{ fps }}</p>
        <p>音频格式：{{ audio }}</p>
        <p>音频采样率：{{ audioRate }}</p>
      </div>
    </div>
    <br />
  </div>
</template>

<script setup lang="ts">
import { onMounted, ref } from 'vue'
import { FFmpeg } from '@ffmpeg/ffmpeg'
import type { LogEvent } from '@ffmpeg/ffmpeg/dist/esm/types'
import { fetchFile, toBlobURL } from '@ffmpeg/util'
import OSS from 'ali-oss'
import axios from 'axios'
import plupload from 'plupload'

const baseURL = 'https://unpkg.com/@ffmpeg/core-mt@0.12.4/dist/esm'
const ffmpeg = new FFmpeg()

const videoSrc = ref('')
const imageSrc = ref('')
const messageText = ref('')
const uploadFileSize = ref('0kb')
const fileSize = ref('0kb')
// 转换进度
const transcodingProgress = ref(0)

const ossParams = ref('')

// 轨道
const track = ref([])
// 文件名
const filename = ref('')
// 时长
const duration = ref('')
// 格式
const majorBrand = ref('')
// 编码器
const encoder = ref('')
// 分辨率
const resolution = ref('')
// 比特率
const bitRate = ref('')
// 帧率
const fps = ref('')
// 音频格式
const audio = ref('')
// 音频采样率
const audioRate = ref('')

let isLoadFfmpegCore = false

let isTranscoding = false

ffmpeg.on('log', (e: any) => {
  console.log('ffmpeg日志', e.message)
  fileInfoFilter(e.message)
})
ffmpeg.on('progress', (e: any) => {
  console.log('ffmpeg 进度', e)
  transcodingProgress.value = filterProgress(e.progress)
})
onMounted(async () => {
  
})

/**
 * 上传文件事件
 * @param e
 */
const handleFileInputChange = async (e: any) => {
  // 重新计时
  resetTime()
  const file = e.target.files[0]
  console.log('文件', file)
  uploadFileSize.value = filterType(file.size)
  const name = file.name.replace(/\.[0-9a-zA-Z]+$/, '')

  const newName = 'cache123'
  console.log('输入文件名', file.name)
  console.log('输出文件名', name)
  // 开始计时
  startTime()

  // 加载ffmpeg
  if (!isLoadFfmpegCore) {
    messageText.value = '加载ffmpeg-core.js'
    await ffmpeg.load({
      coreURL: await toBlobURL(`${baseURL}/ffmpeg-core.js`, 'text/javascript'),
      wasmURL: await toBlobURL(`${baseURL}/ffmpeg-core.wasm`, 'application/wasm'),
      workerURL: await toBlobURL(`${baseURL}/ffmpeg-core.worker.js`, 'text/javascript')
    })
    isLoadFfmpegCore = true
  }
  if (isTranscoding) return
  isTranscoding = true
  console.log('开始上传的文件转码', Date.now())
  messageText.value = '开始上传的文件转码'
  await ffmpeg.writeFile(file.name, await fetchFile(file))

  // 视频截帧
  frameImage(file, newName)

  // 转码
  transcoding(file, newName)
  // 停止计时
  stopTime()
}

/**
 * 视频转码
 * @param file 文件
 * @param newName 新文件名称
 */
const transcoding = async (file: any, newName: string) => {
  // 转码
  await ffmpeg.exec([
    '-y',
    '-i',
    file.name,
    '-c:a',
    'copy',
    '-c:v',
    'libx264',
    '-profile:v',
    'high',
    '-r',
    '30',
    '-crf',
    '30',
    '-s',
    '720x1080',
    `${newName}.mp4`
  ])
  messageText.value = '转码完成'
  console.log('转码完成', Date.now())
  isTranscoding = false
  const data = await ffmpeg.readFile(`${newName}.mp4`)
  console.log('转码完成file', data)
  fileSize.value = filterType(data.length)

  const newData = new Blob([data.buffer], { type: 'video/mp4' })
  // putObject(newData, newName+".mp4")
  videoSrc.value = URL.createObjectURL(newData)
}

/**
 * 视频截帧
 * @param file 文件
 * @param newName 新文件名称
 */
const frameImage = async (file: any, newName: string) => {
  // 截取图片的次数
  const frameCount = 1
  // 截取图片的间隔
  const frameInterval = 5
  // 截帧
  await ffmpeg.exec([
    '-i',
    file.name,
    '-r',
    `${frameInterval}`,
    '-ss',
    '0',
    '-vframes',
    `${frameCount}`,
    '-f',
    'image2',
    '-s',
    '72*108',
    `${newName}.png`
  ])

  // 截帧数据
  const frameData = await ffmpeg.readFile(`${newName}.png`)
  const newData = new Blob([frameData.buffer], { type: 'image/png' })
  // uploadFile(newData, `${newName}.png`, ossParams)
  imageSrc.value = URL.createObjectURL(newData)
}

const handleFileInputClick = (e: any) => {
  e.target.value = ''
}

const fileInfoFilter = (message: string) => {
  // 加载视频时候才处理
  if (message.indexOf('Duration') !== -1) {
    duration.value = message.substring(
      message.indexOf('Duration:') + 'Duration:'.length,
      message.indexOf('Duration:') + 'Duration:'.length + '00:00:20.48'.length
    )
    console.log('时长', duration)
  }
  if (message.indexOf('Duration') !== -1 && message.indexOf('bitrate') !== -1) {
    bitRate.value = message.substring(message.indexOf('bitrate:') + 'bitrate:'.length)
    console.log('比特率', bitRate)
  }
  if (message.indexOf('major_brand') !== -1) {
    let key = 'major_brand:'
    majorBrand.value = message.substring(message.indexOf(key) + key.length)
    console.log('格式', majorBrand)
  }
  if (message.indexOf('encoder') !== -1) {
    let key = 'encoder:'
    encoder.value = message.substring(message.indexOf(key) + key.length)
    console.log('编码器', encoder)
  }
  if (message.indexOf('Video:') !== -1) {
    let key = 'Video:'
    let arr = message.substring(message.indexOf(key) + key.length)
    let arrList = arr.split(',')
    console.log('视频信息', arr)
    resolution.value = arrList[2].substring(0, arrList[2].indexOf('['))
    console.log('分辨率', arr)
    fps.value = arrList[3]
    console.log('帧率', arr)
  }
  if (message.indexOf('Audio:') !== -1) {
    let key = 'Audio:'
    let arr = message.substring(message.indexOf(key) + key.length)
    let arrList = arr.split(',')
    console.log('音频信息', arr)
    audio.value = arrList[0]
    console.log('音频格式', arr)
    audioRate.value = arrList[1]
    console.log('音频采样率', arr)
  }
}

// 计时器
const time = ref(0)
let timer: any
const startTime = () => {
  console.log("startTime")
  if (!timer) {
    console.log("startTime 1")
    timer = setInterval(() => {
      time.value++
      console.log("startTime 2")
    }, 1000)
  }
}
const stopTime = () => {
  console.log("stopTime")
  clearInterval(timer)
  timer = null
}
const resetTime = () => {
  console.log("resetTime")
  stopTime()
  time.value = 0
}

/**
 * 数据转换
 * @param val 转换数据
 */
const filterProgress = (val: number) => {
  return Math.floor(val * 100)
}

/**
 * 数据转换
 * @param val 转换数据
 */
const filterType = (val: number) => {
  if (val === 0) return '0 B'
  var k = 1024
  var sizes = ['B', 'KB', 'MB', 'GB', 'PB', 'TB', 'EB', 'ZB', 'YB'],
    i = Math.floor(Math.log(val) / Math.log(k))
  return (val / Math.pow(k, i)).toPrecision(3) + '' + sizes[i]
}

/**
 * 获取文件长度
 * @param len 名称长度
 */
const randomString = (len: number) => {
  len = len || 32
  var chars = 'ABCDEFGHJKMNPQRSTWXYZabcdefhijkmnprstwxyz2345678'
  var maxPos = chars.length
  var pwd = ''
  for (var i = 0; i < len; i++) {
    pwd += chars.charAt(Math.floor(Math.random() * maxPos))
  }
  return pwd
}

/**
 * 获取文件名称
 * @param filename
 */
const getSuffix = (filename: string) => {
  var pos = filename.lastIndexOf('.')
  var suffix = ''
  if (pos != -1) {
    suffix = filename.substring(pos)
  }
  return suffix
}
</script>

<style scoped>
.video-wrapper {
  width: 100%;
  height: 100%;
}
.i-video {
  width: 100%;
  height: 100%;
}
</style>
